#ifndef __DEFERRED_PIPELINE_H__
#define __DEFERRED_PIPELINE_H__

#include "program.h"
#include "../../Epsilon/Epsilon3D/OpenGL.h"

//// TODO: Depth Precision  - Assume 24-bit by default

class eTB_DeferredPipeline
{
public:
  eTB_DeferredPipeline (int x = 0, int y = 0)
  {
    rb_depth_ = rb_normal_ = rb_diffuse_
              = NULL;

    depth_ = normal_ = diffuse_
           = NULL;

    x_res_     = x;
    y_res_     = y;
    res_scale_ = 1.0f;

    active_ = false;

    prg_depth_debug_ = NULL;
    vs_depth_debug_  = NULL;
    ps_depth_debug_  = NULL;

    prg_setup_ = NULL;
    vs_setup_  = NULL;
    ps_setup_  = NULL;

    // After prg_setup_ is loaded, this will point to
    //   the uniform that identifies the diffuse texture's
    //     bound texture unit (which is always 0...)
    diffuse_sampler_ = NULL;

    normal_map_id_ = 0;
  }

  virtual ~eTB_DeferredPipeline (void);

  bool init     (void);
  bool shutdown (void);

  void resize   (int x, int y);

  void start  (void);
  void finish (void);

  void draw_debug (void);

//protected:

//private:
  // Tie to an e3dRenderContext...

  GLuint fb_;
  GLuint composite_fb_;

  GLuint rb_depth_;
  GLuint rb_normal_;
  GLuint rb_diffuse_;
  GLuint rb_ambient_;

  GLuint composite_; // Composited texture
  GLuint glow_;      // Glow calculated during compositing

  GLuint depth_;
  GLuint normal_;
  GLuint diffuse_;
  GLuint ambient_;

  GLuint x_res_;
  GLuint y_res_;
  float  res_scale_; // Adjust the framebuffer resolution independantly from
                     //   the viewport if not 1.0...

  bool   active_;

  eTB_Program* prg_depth_debug_;

  eTB_Shader* vs_depth_debug_;
  eTB_Shader* ps_depth_debug_;


  eTB_Program* prg_setup_;

  eTB_Shader* vs_setup_;
  eTB_Shader* ps_setup_;

  eTB_Program* prg_composite_;

  eTB_Shader* vs_composite_;
  eTB_Shader* ps_composite_;

  // TODO, silly way of initializing the sampler...
  GLuint diffuse_sampler_;
  GLuint normal_sampler_;

  // Samplers used for the deferred shading compositer
  GLuint diffuse_buffer_;
  GLuint ambient_buffer_;
  GLuint depth_buffer_;
  GLuint normal_buffer_;

  GLuint light_pos_;
  GLuint light_count_;
  GLuint light_color_;

  GLuint proj_mat_;
  GLuint mv_mat_;

  GLuint ssao_; /* Tells the compositer shader whether or not to perform
                     the Screen Space Ambient Occlusion pre-processing stage. */

  float proj_ [16];
  float mv_   [16];

  int    normal_map_id_;
};

#endif /* __DEFERRED_PIPELINE_H__ */